#ifndef __MY_DATA__ // 防止头文件重复包含
#define __MY_DATA__

#include <unordered_map> // 使用哈希表存储备份信息
#include <pthread.h>     // 用于线程安全操作
#include "util.hpp"      // 工具类头文件
#include "config.hpp"    // 配置类头文件

namespace cloud // 定义在cloud命名空间中
{
    typedef struct BackupInfo // 备份信息结构体
    {
        bool pack_flag;        // 是否已压缩标志
        size_t fsize;          // 文件大小
        time_t mtime;          // 最后修改时间
        time_t atime;          // 最后访问时间
        std::string real_path; // 文件真实路径
        std::string pack_path; // 打包后文件路径
        std::string url;       // 下载URL路径

        // 根据真实路径创建新的备份信息
        bool NewBackupInfo(const std::string &realpath)
        {
            FileUtil fu(realpath);    // 使用文件工具类
            if (fu.Exists() == false) // 检查文件是否存在
            {
                std::cout << "new backupinfo: file not exists!\n";
            }
            // 获取配置单例
            Config *config = Config::GetInstance();

            // 从配置中获取各个信息
            std::string packdir = config->GetPackDir();
            std::string packsuffix = config->GetPackFileSuffix();
            std::string download_prefix = config->GetDownloadPrefix();

            // 设置备份信息各字段
            this->pack_flag = false;      // 初始未打包
            this->fsize = fu.FileSize();  // 获取文件大小
            this->mtime = fu.LastMTime(); // 获取最后修改时间
            this->atime = fu.LastATime(); // 获取最后访问时间
            this->real_path = realpath;   // 设置真实路径

            // 构建打包路径：./backdir/a.txt ->./packdir/a.txt.lz
            this->pack_path = packdir + fu.FileName() + packsuffix;

            // 构建下载URL: ./backdir/a.txt -> /dowmload/a.txt
            this->url = download_prefix + fu.FileName();

            return true;
        }
    } BackupInfo;

    // 数据管理类
    class DataManager
    {
    private:
        std::string _backup_file;                           // 备份数据存储文件路径
        pthread_rwlock_t _rwlock;                           // 读写锁，读共享，写互斥，保证线程安全
        std::unordered_map<std::string, BackupInfo> _table; // 哈希表存储便于查找

    public:
        // 构造函数
        DataManager()
        {
            // 从配置信息获取备份文件路径
            _backup_file = Config::GetInstance()->GetBackupFile();
            pthread_rwlock_init(&_rwlock, nullptr); // 初始化读写锁
            InitLoad();                             // 初始化时加载已有数据
        }
        // 析构函数
        ~DataManager()
        {
            pthread_rwlock_destroy(&_rwlock); // 销毁读写锁
        }
        // 插入备份信息
        bool Insert(const BackupInfo &info)
        {
            pthread_rwlock_wrlock(&_rwlock); // 加写锁
            _table[info.url] = info;         // 插入数据
            pthread_rwlock_unlock(&_rwlock); // 解写锁
            Storage();                       // 持久化存储
            return true;
        }
        // 更新备份信息
        bool Update(const BackupInfo &info)
        {
            pthread_rwlock_wrlock(&_rwlock); // 加写锁
            _table[info.url] = info;         // 插入数据
            pthread_rwlock_unlock(&_rwlock); // 解写锁
            Storage();                       // 持久化存储
            return true;
        }
        // 通过URL获取单个备份信息
        bool GetOneByURL(const std::string &url, BackupInfo *info)
        {
            pthread_rwlock_wrlock(&_rwlock); // 加写锁
            auto it = _table.find(url);      // 查找URL对应的备份信息
            if (it == _table.end())          // 未找到
            {
                pthread_rwlock_unlock(&_rwlock); // 解写锁
                return false;
            }
            *info = it->second;              // 找到赋值给输出参数
            pthread_rwlock_unlock(&_rwlock); // 解写锁
            return true;
        }
        // 通过真实路径获取单个备份信息
        bool GetOneByRealPath(const std::string &realpath, BackupInfo *info)
        {
            pthread_rwlock_wrlock(&_rwlock); // 加写锁
            auto it = _table.begin();
            for (; it != _table.end(); ++it)
            {
                // 遍历查找
                if (it->second.real_path == realpath)
                {
                    *info = it->second;              // 找到赋值给输出参数
                    pthread_rwlock_unlock(&_rwlock); // 解写锁
                    return true;
                }
            }
            // 未找到
            pthread_rwlock_unlock(&_rwlock); // 解写锁
            return false;
        }
        // 获取所有备份信息
        bool GetAll(std::vector<BackupInfo> *arry)
        {
            pthread_rwlock_wrlock(&_rwlock); // 加写锁
            auto it = _table.begin();
            for (; it != _table.end(); ++it)
            {
                arry->push_back(it->second); // 添加到输出数组
            }
            pthread_rwlock_unlock(&_rwlock); // 解写锁
            return true;
        }
        // 持久化存储数据到文件
        bool Storage()
        {
            // 1.获取所有数据
            std::vector<BackupInfo> arry;
            this->GetAll(&arry);

            // 2.转换为Json格式
            Json::Value root;
            for (int i = 0; i < arry.size(); i++)
            {
                Json::Value item;
                item["pack_flag"] = arry[i].pack_flag;
                item["fsize"] = (Json::Int64)arry[i].fsize;
                item["atime"] = (Json::Int64)arry[i].atime;
                item["mtime"] = (Json::Int64)arry[i].mtime;
                item["real_path"] = arry[i].real_path;
                item["pack_path"] = arry[i].pack_path;
                item["url"] = arry[i].url;
                root.append(item); // 添加数组元素
            }

            // 3.序列化为字符串
            std::string body;
            JsonUtil::Serialize(root, &body);

            // 4.写入文件
            FileUtil fu(_backup_file);
            fu.SetContent(body);
            return true;
        }

        // 从文件初始化加载数据
        bool InitLoad()
        {
            // 1. 检查数据文件是否存在
            FileUtil fu(_backup_file);
            if (fu.Exists() == false)
            {
                return true; // 文件不存在直接返回
            }

            // 读取文件内容
            std::string body;
            fu.GetContent(&body);

            // 2.反序列化为Json格式
            Json::Value root;
            JsonUtil::UnSerialize(body, &root);

            // 3. 将Json数据加载到内存表中
            for (int i = 0; i < root.size(); i++)
            {
                BackupInfo info;
                info.pack_flag = root[i]["pack_flag"].asBool();
                info.fsize = root[i]["fsize"].asInt64();
                info.atime = root[i]["atime"].asInt64();
                info.mtime = root[i]["mtime"].asInt64();
                info.pack_path = root[i]["pack_path"].asString();
                info.real_path = root[i]["real_path"].asString();
                info.url = root[i]["url"].asString();
                Insert(info); // 插入到表中
            }

            return true;
        }
    };

}

#endif